import 'dart:collection';

class Person {
  final String name;
  final int age;

  Person(this.name, this.age);

  // Override equals: Compare objects by properties
  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) return false;
    return other is Person && other.name == name && other.age == age;
  }

  // Override hashCode: Ensure same properties produce same hash
  @override
  int get hashCode => Object.hash(name, age);

  // Optional: Custom string representation
  @override
  String toString() => '$name, $age';
}

// ----------------------
// 2. Comparison between Set and List
// ----------------------
void main() {
  // ----------------------
  // Scenario 1: Automatic Duplicate Removal
  // ----------------------
  print("===== Scenario 1: Automatic Duplicate Removal =====");

  // List (allows duplicates)
  List<String> fruitList = ['Apple', 'Banana', 'Apple'];
  print(
    "List content (allows duplicates): $fruitList",
  ); // Output: [Apple, Banana, Apple]

  // Set (automatically removes duplicates)
  Set<String> fruitSet = {'Apple', 'Banana', 'Apple'};
  print(
    "Set content (duplicates removed): $fruitSet",
  ); // Output: {Apple, Banana}

  // ----------------------
  // Scenario 2: Efficient Element Existence Check
  // ----------------------
  print("\n===== Scenario 2: Check Element Existence =====");

  // Simulate a whitelist (Set has O(1) lookup efficiency)
  Set<String> whitelist = {'admin', 'user', 'guest'};

  String userInput = 'user';
  bool isAllowed = whitelist.contains(userInput);
  print("Is '$userInput' in the whitelist? $isAllowed"); // Output: true

  // ----------------------
  // Scenario 3: Storing Custom Objects
  // ----------------------
  print("\n===== Scenario 3: Storing Custom Objects =====");

  Set<Person> people = {
    Person('Alice', 20),
    Person('Bob', 25),
    Person('Alice', 20), // Duplicate (same properties), will be removed
    Person('Charlie', 30),
  };

  print("Set content with custom objects:");
  people.forEach((person) => print("- ${person.toString()}"));
  // Output example (order not guaranteed):
  // - Alice, 20
  // - Bob, 25
  // - Charlie, 30

  // ----------------------
  // Scenario 4: Ordered Set (LinkedHashSet maintains insertion order)
  // ----------------------
  print("\n===== Scenario 4: Ordered Set (LinkedHashSet) =====");

  // Use LinkedHashSet to maintain insertion order
  var orderedSet = LinkedHashSet<String>();
  orderedSet.add('C');
  orderedSet.add('A');
  orderedSet.add('B');

  print("Ordered Set content: ${orderedSet.toList()}"); // Output: [C, A, B]
}
